package com.mmloo.common.repository;

import com.lovver.ssdbj.core.BaseResultSet;
import com.lovver.ssdbj.exception.SSDBException;
import com.lovver.ssdbj.pool.SSDBPoolConnection;
import com.mmloo.common.exception.MMLOOException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 封装数据库操作语句
 * Created by jessy on 2015/8/4.
 */
@Repository
public class CURDRepository {


    BasicRepository basicRepository = new BasicRepository();
    SSDBPoolConnection conn = null;

    Logger logger = LoggerFactory.getLogger(BasicRepository.class);

    private void connect()throws Exception{
        conn = basicRepository.init();
    }

    public void incr(ArrayList<byte[]> mset_params) throws Exception{
        if (mset_params != null && mset_params.size() > 0) {
            connect();
            if (conn != null)
                try {
                    conn.executeUpdate("incr", mset_params);
                    logger.debug("Value increase success");
                } catch (SSDBException e) {
                    logger.debug("Value increase fail ");
                    throw new MMLOOException("数据自增失败" + e.getCause());

                }
        }
    }

    /**
     * 根据指定key获取value
     * @param get_params
     * @return
     */
    public String get(ArrayList<byte[]> get_params) throws Exception {
        if (get_params != null && get_params.size() > 0) {
            connect();
            if (conn != null)
                try {
                    BaseResultSet<byte[]> m_rs = conn.execute("get",
                            get_params);
                    if(m_rs.getResult() != null) {
                        logger.debug("get KV value success");
                        return new String(m_rs.getResult());
                    }else{
                        return null;
                    }
                } catch (SSDBException e) {
                    logger.debug("get KV value fail ");
                    throw new MMLOOException("根据指定key获取value失败" + e.getCause());
                }
        }
        return null;

    }

    /**
     * KV操作
     * 键--值
     * 说明：键值对存储，新值会覆盖
     * multi_set
     * 多个KEY-VALUE输入
     */
    public void mset(ArrayList<byte[]> mset_params) throws Exception {
        if (mset_params != null && mset_params.size() > 0) {
            connect();
            if (conn != null)
                try {
                    conn.executeUpdate("multi_set", mset_params);
                    logger.debug("multi value set success");
                } catch (SSDBException e) {
                    logger.debug("multi value set fail");
                    throw new MMLOOException("键值存储失败" + e.getCause());
                }
        }
    }

    /**
     * multi_get
     * 多个VALUE获取
     */
    public Map<String,String> mget(ArrayList<byte[]> mget_params) throws Exception {
        if (mget_params != null && mget_params.size() > 0) {
            connect();
            if (conn != null) {
                try {
                    BaseResultSet<Map<byte[], byte[]>> m_rs = conn.execute("multi_get",
                            mget_params);
                    if(m_rs.getResult() != null) {
                        Map<byte[], byte[]> items = m_rs.getResult();
                        Map<String, String> returnData = new HashMap();
                        Iterator<byte[]> ite = items.keySet().iterator();
                        while (ite.hasNext()) {
                            byte[] key = ite.next();
                            logger.debug("get key = " + key + " 其value为 " + items.get(key));
                            returnData.put(key.toString(), items.get(key).toString());
                        }
                        return returnData;
                    }else {
                        logger.debug("do not exist the data ");
                    }
                } catch (SSDBException e) {
                    throw new MMLOOException("多值获取失败" + e.getCause());
                }
            }
            logger.debug("get fail.");
        }
        return null;
    }

    /**
     * scan
     * 列出K-V列表
     */
    public Map<String, String> scanAll() throws Exception {

        connect();
        if (conn != null) {
            try {
                ArrayList<byte[]> scan_params = new ArrayList();
                scan_params.add("".getBytes());
                scan_params.add("".getBytes());
                scan_params.add("-1".getBytes());
            /*执行命令*/
                BaseResultSet scan_rs = null;
                scan_rs = conn.execute("scan",
                        scan_params);
                if(scan_rs.getResult() != null) {
                    Map<byte[], byte[]> scan_items = (Map<byte[], byte[]>) scan_rs.getResult();
                    Map<String, String> returnData = new HashMap();
                    logger.debug("get K-V all datas");
			/*分析结果*/
                    Iterator<byte[]> scan_ite = scan_items.keySet().iterator();
                    while (scan_ite.hasNext()) {
                        byte[] key = scan_ite.next();
                        logger.debug("key = " + key + " 其value为 " + scan_items.get(key));
                        returnData.put(key.toString(), scan_items.get(key).toString());
                    }
                    return returnData;
                }else{
                    return null;
                }
            } catch (SSDBException e) {
                throw new MMLOOException("浏览键值所有数据失败" + e.getCause());
            }
        }
        return null;
    }

    /**
     * rscanAll 反向遍历KV表
     * @return
     */
    public Map<String, String> rscanAll() throws Exception {
        connect();
        if (conn != null) {
            try {
                ArrayList<byte[]> scan_params = new ArrayList();
                scan_params.add("".getBytes());
                scan_params.add("".getBytes());
                scan_params.add("-1".getBytes());
            /*执行命令*/
                BaseResultSet<Map<byte[], byte[]>> scan_rs = null;
                scan_rs = conn.execute("rscan",
                        scan_params);
                if(scan_rs.getResult() != null) {
                    Map<byte[], byte[]> scan_items = scan_rs.getResult();
                    Map<String, String> returnData = new HashMap();
                    logger.debug("反向列出K-V列表所有数据");
			/*分析结果*/
                    Iterator<byte[]> scan_ite = scan_items.keySet().iterator();
                    while (scan_ite.hasNext()) {
                        byte[] key = scan_ite.next();
                        logger.debug("key = " + key + " 其value为 " + scan_items.get(key));
                        returnData.put(key.toString(), scan_items.get(key).toString());
                    }
                    return returnData;
                }else{
                    return null;
                }
            } catch (SSDBException e) {
                throw new MMLOOException("反向遍历键值所有数据失败" + e.getCause());
            }
        }
        return null;
    }


    /**
     * hscan
     * 列出指定hashmap名的数据列表
     */
    public Map<String, String> hscanAll(String hashmap) throws Exception {

        connect();
        if (conn != null) {
            try {
                ArrayList<byte[]> hscan_params = new ArrayList();
                hscan_params.add(hashmap.getBytes());
                hscan_params.add("".getBytes());
                hscan_params.add("".getBytes());
                hscan_params.add("-1".getBytes());
            /*执行命令*/
                BaseResultSet<Map<byte[], byte[]>> scan_rs = null;
                scan_rs = conn.execute("hscan", hscan_params);
                if(scan_rs.getResult() != null) {
                    Map<byte[], byte[]> scan_items = scan_rs.getResult();
                    Map<String, String> returnData = new HashMap();
                    if (scan_items.size() > 0) {
                        logger.debug("列出 " + hashmap + " 表所有数据");
			/*分析结果*/
                        Iterator<byte[]> scan_ite = scan_items.keySet().iterator();
                        while (scan_ite.hasNext()) {
                            byte[] key = scan_ite.next();
                            System.out.println("key = " + new String(key) + " 其value为 " + new String(scan_items.get(key)));
                            logger.debug("key = " + new String(key) + " 其value为 " + new String(scan_items.get(key)));
                            returnData.put(new String(key), new String(scan_items.get(key)));
                        }
                    }
                    return returnData;
                }else{
                    return null;
                }
            } catch (SSDBException e) {
                throw new MMLOOException("列出指定hashmap名的数据列表 失败" + e.getCause());
            }
        }
        return null;
    }

    public Map<String, String> hgetAll(String hashmap) throws Exception {
        connect();
        if (conn != null) {
            try {
                ArrayList<byte[]> hgetAll_params = new ArrayList();
                hgetAll_params.add(hashmap.getBytes());
                System.out.println("1--- " + conn.executeUpdate("hgetall", hgetAll_params));
                BaseResultSet<Map<byte[], byte[]>> getAll_rs = conn.execute("hgetall", hgetAll_params);
                Map<byte[], byte[]> get_items = getAll_rs.getResult();
                System.out.println("get items >> " + get_items);
            } catch (SSDBException e) {
                throw new MMLOOException("获取指定hashmap名的数据列表 失败" + e.getCause());
            }catch (Exception e){
                throw new MMLOOException("获取指定hashmap名的数据列表 失败" + e.getCause());
            }
        }
        return null;
    }

    /**
     * Hmap操作
     * 表名--键--值
     * 说明：多格式哈希表，新值会覆盖
     */
    public void hset(ArrayList<byte[]> hset_params) throws Exception {
        if(hset_params != null && hset_params.size()>0) {
            connect();
            if (conn != null)
                try {
                    conn.executeUpdate("hset", hset_params);
                    logger.debug("Hmap set success");
                } catch (SSDBException e) {
                    logger.debug("Hmap set fail");
                    throw new MMLOOException("多格式哈希表设置值 失败" + e.getCause());
                }
        }
    }

    /**
     * hget
     */
    public String hget(ArrayList<byte[]> hget_params) throws Exception {
        if(hget_params != null && hget_params.size()>0) {
            connect();
            if (conn != null) {
                try {
                    BaseResultSet<byte[]> rs = conn.execute("hget", hget_params);
                    if(rs != null) {
                        logger.debug("Hmap get success");
                        return new String(rs.getResult());
                    }else{
                        logger.debug("do not exist the data");
                        return null;
                    }
                } catch (SSDBException e) {
                    logger.debug("Hmap get fail");
                    throw new MMLOOException("多格式哈希表获取值 失败" + e.getCause());
                }
            }
        }
        return null;
    }




    /** zmap
     * 表名--键--值
     * 说明：自动排序数据，新值会覆盖

     *
     * zset*/
    public void zset(ArrayList<byte[]> zset_params) throws Exception {
        if(zset_params != null && zset_params.size()>0) {
            connect();
            if (conn != null)
                try {
                    conn.executeUpdate("zset", zset_params);
                    logger.debug("zmap set success");
                } catch (SSDBException e) {
                    logger.debug("zmap set fail");
                    throw new MMLOOException("zmap设置值 失败" + e.getCause());
                }
        }
    }

    /**
     * zget
     * @param zget_params
     * @return
     */
    public String zget(ArrayList<byte[]> zget_params) throws Exception {
        if(zget_params != null && zget_params.size()>0) {
            connect();
            if (conn != null) {
                try {
                    BaseResultSet<byte[]> rzget = conn.execute("zget", zget_params);
                    if(rzget.getResult() != null) {
                        byte[] result = rzget.getResult();
                        logger.debug("zmap get success");
                        return new String(result);
                    }else{
                        return null;
                    }
                } catch (SSDBException e) {
                    logger.debug("zmap get fail");
                    throw new MMLOOException("zmap获取值 失败" + e.getCause());
                }
            }
        }
        return null;
    }

    /**
     * 删除 zset中指定的key
     * @param setName
     * @param key
     */
    public void zdel(String setName,String... key) throws Exception {
        if(!StringUtils.isEmpty(setName) && key != null){
            connect();
            if (conn != null) {
                try {
                    ArrayList<byte[]> zdel_params = new ArrayList<>();
                    zdel_params.add(setName.getBytes());
                    for (String k : key) {
                        if (!StringUtils.isEmpty(k))
                            zdel_params.add(k.getBytes());
                    }
                    conn.executeUpdate("zdel", zdel_params);
                    logger.debug("delete " + setName + " success");
                } catch (SSDBException e) {
                    throw new MMLOOException("删除 zset中指定的key 失败" + e.getCause());
                }
            }
        }
    }



    /**
     * Qstack操作
     * 说明：队列操作
     *
     * qset
     */
    public void qset(ArrayList<byte[]> qset_params) throws Exception {
        if(qset_params != null && qset_params.size()>0) {
            connect();
            if (conn != null)
                try {
                    conn.executeUpdate("qset", qset_params);
                    logger.debug("Qstack set success");
                } catch (SSDBException e) {
                    logger.debug("Qstack set fail");
                    throw new MMLOOException("队列操作 设置值 失败" + e.getCause());
                }
        }
    }

    /**
     *
     * qget
     * @param qget_params
     * @return
     */
    public String qget(ArrayList<byte[]> qget_params) throws Exception {
        if(qget_params != null && qget_params.size()>0) {
            connect();
            if (conn != null) {
                try {
                    BaseResultSet<byte[]> rzget = conn.execute("qget", qget_params);
                    if(rzget.getResult() != null) {
                        byte[] result = rzget.getResult();
                        logger.debug("Qstack get success");
                        return new String(result);
                    }else{
                        return null;
                    }
                } catch (SSDBException e) {
                    logger.debug("Qstack get fail");
                    throw new MMLOOException("队列操作 获取值 失败" + e.getCause());
                }
            }
        }
        return null;
    }

    /**
     * 删除指定key的记录
     * @param key
     */
    public void del(String key) throws Exception {
        if(!StringUtils.isEmpty(key)) {
            connect();
            if (conn != null) {
                try {
                    ArrayList<byte[]> del_params = new ArrayList<>();
                    del_params.add(key.getBytes());
                    conn.executeUpdate("del", del_params);
                    logger.debug("delete key  " + key + " data");
                    System.out.println("delete key  " + key + " data");
                } catch (SSDBException e) {
                    logger.debug("delete  key  " + key + " fail");
                    System.out.println("delete  key  " + key + " fail");
                    throw new MMLOOException("删除指定key的记录 失败" + e.getCause());
                }
            }
        }
    }

    /**
     * 批量删除一批key及其对应的值内容
     * @param del_keys
     */
    public void multi_del(ArrayList<byte[]> del_keys) throws Exception {
        if(del_keys != null && del_keys.size()>0) {
            connect();
            if (conn != null) {
                try {
                    conn.executeUpdate("multi_del", del_keys);
                    for (byte[] key : del_keys)
                        logger.debug("删除key为 " + key + "的记录");
                } catch (SSDBException e) {
                    for (byte[] key : del_keys)
                        logger.debug("删除 key 为 " + key + " 的数据失败");
                    throw new MMLOOException("批量删除一批key及其对应的值内容 失败" + e.getCause());
                }
            }
        }
    }
    /**
     * 批量删除指定hashmap中的key及其对应的值内容
     * @param del_keys
     */
    public void multi_hdel(String hashmap,String... del_keys) throws Exception {
        if(!StringUtils.isEmpty(hashmap)) {
            connect();
            if (conn != null) {
                try {
                    ArrayList<byte[]> del_params = new ArrayList<>();
                    del_params.add(hashmap.getBytes());
                    for(String k : del_keys){
                        if(!StringUtils.isEmpty(k))
                            del_params.add(k.getBytes());
                    }
                    conn.executeUpdate("multi_hdel", del_params);
                    logger.debug("删除表 " + hashmap + "的记录");
                } catch (SSDBException e) {
                    logger.debug("删除表 " + hashmap + " 的数据失败");
                    throw new MMLOOException("批量删除指定hashmap中的key及其对应的值内容 失败" + e.getCause());
                }
            }
        }
    }

    /**
     * 批量获取指定hashmap中的key及其对应的值内容
     * @param get_keys
     */
    public void multi_hgetel(String hashmap,String... get_keys) throws Exception {
        if(!StringUtils.isEmpty(hashmap)) {
            connect();
            if (conn != null) {
                try {
                    ArrayList<byte[]> get_params = new ArrayList<>();
                    get_params.add(hashmap.getBytes());
                    for(String k : get_keys){
                        if(!StringUtils.isEmpty(k))
                            get_params.add(k.getBytes());
                    }
                    BaseResultSet<byte[]> rhget = conn.execute("multi_hget", get_params);
                    System.out.println("rhget > " + rhget);
                    logger.debug("获取表 " + hashmap + "的记录");
                } catch (SSDBException e) {
                    logger.debug("获取表 " + hashmap + " 的数据失败");
                    throw new MMLOOException("批量获取指定hashmap中的key及其对应的值内容 失败" + e.getCause());
                }
            }
        }
    }

    /**
     * 列出 hashmap 中处于区间 (key_start, key_end] 的 key 列表.
     * @param hashmap
     * @param key_start
     * @param key_end
     * @param limit
     * @return
     */
    public String hkeys(String hashmap,String key_start,String key_end,String limit) throws Exception {
        if(!StringUtils.isEmpty(hashmap)){
            connect();
            if (conn != null) {
                try {
                    ArrayList<byte[]> hkeys_params = new ArrayList<>();
                    hkeys_params.add(hashmap.getBytes());
                    hkeys_params.add(key_start.getBytes());
                    hkeys_params.add(key_end.getBytes());
                    hkeys_params.add(limit.getBytes());
                    BaseResultSet<byte[]> resultSet = conn.execute("hkeys", hkeys_params);
                    if(resultSet.getResult() != null) {
                        return new String(resultSet.getResult());
                    }else{
                        return null;
                    }
                } catch (SSDBException e) {
                    throw new MMLOOException("列出 hashmap 中处于区间 (key_start, key_end] 的 key 列表 失败" + e.getCause());
                }
            }
        }
        return null;
    }

    /**
     * hkeys 获取hashmap所有key列表
     * @param hashmap
     * @return
     */
    public String hkeysAll(String hashmap) throws Exception {
        return hkeys(hashmap,"","","");
    }

    /**
     * 删除指定hmap名和keys的数据
     * @param del_map_keys 包含 name - hashmap 的名字.
    key - hashmap 中的 key.
     */
    public void hdel(ArrayList<byte[]> del_map_keys) throws Exception {
        if(del_map_keys != null && del_map_keys.size()>0) {
            connect();
            if (conn != null) {
                try {
                    conn.executeUpdate("hdel", del_map_keys);
                    logger.debug("删除key为 " + del_map_keys.get(0) + "的记录");
                } catch (SSDBException e) {
                    logger.debug("删除 key 为 " + del_map_keys.get(0) + " 的数据失败");
                    throw new MMLOOException("删除指定hmap名和keys的数据 失败" + e.getCause());
                }
            }
        }
    }


}
